﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Windows.Forms;
using IISAutoDeployment.Properties;
using Microsoft.Practices.EnterpriseLibrary.ExceptionHandling;
using Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using Microsoft.Practices.EnterpriseLibrary.Logging.Formatters;
using Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners;

namespace IISAutoDeployment
{
    class Startup
    {
        public static void StartApp()
        {
            BootstrapEnterpriseLibrary();

            Application.ThreadException += Application_ThreadException;
            AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;

            //Application.Run();
        }

        private static LoggingConfiguration BuildLoggingConfiguration()
        {
            var formatter = new TextFormatter(@"Timestamp: {timestamp}{newline} Message: {message}{newline}Category: {category}{newline} Priority: {priority}{newline}EventId: {eventid}{newline} Severity: {severity}{newline}Title:{title}{newline} Machine: {localMachine}{newline} App Domain: {localAppDomain}{newline} ProcessId: {localProcessId}{newline} Process Name: {localProcessName}{newline} Thread Name: {threadName}{newline} Win32 ThreadId: {win32ThreadId}{newline} Extended Properties: {dictionary({key} - {value}{newline})}");

            var flatFileTraceListener = new FlatFileTraceListener(@"C:\Temp\Puzzler.log", "----------------------------------------", "----------------------------------------", formatter);
            var eventLog = new EventLog("Application", ".", "Enterprise Library Logging");
            var eventLogTraceListener = new FormattedEventLogTraceListener(eventLog);

            // Build Configuration 
            var config = new LoggingConfiguration();
            config.AddLogSource("General", SourceLevels.All, true)
                .AddTraceListener(eventLogTraceListener);

            config.LogSources["General"]
                .AddTraceListener(flatFileTraceListener);

            // Special Sources Configuration 
            config.SpecialSources.LoggingErrorsAndWarnings
               .AddTraceListener(eventLogTraceListener);

            return config;
        }

        private static void BootstrapEnterpriseLibrary()
        {
            Logger.SetLogWriter(new LogWriter(BuildLoggingConfiguration()));
            var uiPolicies = new List<ExceptionPolicyEntry> { 
                new ExceptionPolicyEntry( typeof(Exception), 
                    PostHandlingAction.None, 
                    new IExceptionHandler[] { 
                        new LoggingExceptionHandler(
                            "General", 100, TraceEventType.Error, 
                            "Enterprise Library Exception Handling", 
                            0, 
                            typeof(TextExceptionFormatter), 
                            Logger.Writer) 
                    }) 
            };
            var policies = new List<ExceptionPolicyDefinition>
            {
                new ExceptionPolicyDefinition("UI Policy", uiPolicies),
            };

            ExceptionPolicy.SetExceptionManager(new ExceptionManager(policies));
        }

        public static void HandleException(Exception ex, string policy)
        {
            bool rethrow;
            try
            {
                rethrow = ExceptionPolicy.HandleException(ex, policy);
            }
            catch (Exception innerEx)
            {
                string errorMsg = "An unexpected expection occured while calling HandleException with policy '" + policy +
                                  "'.";
                errorMsg += Environment.NewLine + innerEx;

                MessageBox.Show(errorMsg, Resources.Startup_HandleException_Application_Error, MessageBoxButtons.OK, MessageBoxIcon.Stop);

                throw ex;
            }

            if (rethrow)
            {
                // this will truncate the stack of the exception
                throw ex;
            }
            MessageBox.Show(Resources.Startup_HandleException_An_unhandled_expection_occured_and_has_been_logged_);
        }

        static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
        {
            HandleException(e.Exception, "UI Policy");
        }

        static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            Exception exception = e.ExceptionObject as Exception;
            if (exception != null)
            {
                HandleException(exception, "Unhandled Policy");
            }
        }
    }
}
